
#include "..\ImageFratory.h"
#include "MandelbrotFactory.h"
#include "julia.h"
#include <iostream>
boost::mutex Mutex::thread_count_mutex;
boost::mutex Mutex::dictionary_mutex;
boost::condition_variable Mutex::thread_created_condition;
boost::mutex Mutex::thread_create_mutex;
boost::barrier Mutex::run_thread_barrier(20);
boost::mutex Mutex::cout_mutex;
int Global::thread_count=0;
const int MAX_THREAD_COUNT=20;
using namespace std;
enum{
    NONE,
    INNER,
    EXTENT,
} point_state;
Julia_Set_Info CreateJuliaParame(double x,double y,double x_scale,double y_scale,int width,int height)
{
    Julia_Set_Info ret;
    ret.c=complex<double>(x,y);
    ret.width=width;
    ret.height=height;
    ret.x_scale=x_scale;
    ret.y_scale=y_scale;
    return ret;

}
int main()
{
    cout<<"start\n";
    Mandelbrot_Set_Info MandelbrotParmae;
    //
    MandelbrotParmae.width=256;
    MandelbrotParmae.height=256;
    MandelbrotParmae.centen_x=0.0;
    MandelbrotParmae.centen_y=0.0;
    MandelbrotParmae.x_scale=3.0/256;
    MandelbrotParmae.y_scale=3.0/MandelbrotParmae.height;
    //
    Image *pMandelbrotImage=MandelbrotFactory<Image>::CreateImage(MandelbrotParmae);
    //ImageFactory::SaveToFile(pMandelbrotImage,"Mandelbrot.txt");
    Mutex::cout_mutex.lock();
    cout<<"Mandelbort is created\n";
    Mutex::cout_mutex.unlock();

    point_state=NONE;
    boost::thread_group myGroup;
    pair<int,int> point;
    double x_left=MandelbrotParmae.centen_x-((MandelbrotParmae.width-1)/2)*MandelbrotParmae.x_scale;
    double y_top=MandelbrotParmae.centen_y+(MandelbrotParmae.height-1)/2*MandelbrotParmae.y_scale;
    int thread_num=0;
    bool break_flag=false;
    for(int i=0;i<pMandelbrotImage->GetHeight();++i){
        point_state=NONE;
        for(int j=0;j<pMandelbrotImage->GetWidth();++j){
            point.first=-1;
            point.second=-1;
            switch(point_state){
                case NONE:
                    if(pMandelbrotImage->GetValue(i,j)==0){
                        point_state=EXTENT;
                    }else{
                        point=make_pair<int,int>(i,j);
                        point_state=INNER;
                    }
                    break;
                case INNER:
                    if(pMandelbrotImage->GetValue(i,j)==0){
                        point=make_pair<int,int>(i,j-1);
                        point_state=EXTENT;
                    }
                    break;
                case EXTENT:
                    if(pMandelbrotImage->GetValue(i,j)==1){
                        point=make_pair<int,int>(i,j);
                        point_state=INNER;
                    }
                    break;
            }
            if(point.first>=0 && point.first<pMandelbrotImage->GetHeight() && point.second>=0  && point.second<pMandelbrotImage->GetWidth()){
                Mutex::cout_mutex.lock();
                cout<<"the main thread is create the thread::"<<thread_num<<endl;
                Mutex::cout_mutex.unlock();
                boost::unique_lock<boost::mutex> cond_lock(Mutex::thread_count_mutex);
                while(Global::thread_count>=MAX_THREAD_COUNT){
                    Mutex::thread_created_condition.wait(cond_lock);
                }
                Global::thread_count+=1;
                cond_lock.unlock();
                Julia_Set_Info info=CreateJuliaParame(j*MandelbrotParmae.x_scale+x_left,y_top-i*MandelbrotParmae.y_scale,3.0/256,3.0/256,256,256);
                myGroup.create_thread(JuliaThread(info,thread_num++));
                break_flag=true;
            }
        }
       if(break_flag) break;
    }
    myGroup.join_all();
    ofstream fout("dictionary.txt");
    for(int i=0;i<65536;++i){
        for(int j=0;j<dictionary_block_number[i];++j){
            fout<<dictionary[i][j]<<endl;
        }
    }
}
